﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Transactions;

using iTool.Cloud.Database.iToolService;
using iTool.Cloud.Database.KeyGeneratorProvider.Contract;
using iTool.Cloud.Database.Options;
using iTool.ClusterComponent;

using Microsoft.Data.Sqlite;
using Microsoft.Extensions.Options;

using Orleans.Concurrency;
using Orleans.Configuration;

namespace iTool.Cloud.Database.ServiceProvider.Implementation
{
    /// <summary>
    /// 广播节点
    /// </summary>
    [Reentrant]
    [ClusterPlacementStrategy]
    public class TransactionService : iToolServiceBase, iTransactionService
    {
        const string DirectoryPath = "./Storage";
        const string DataSourceTransaction = DirectoryPath + "/DataBase.transaction";
        const string DataSource = DirectoryPath + "/DataBase.master";
        readonly string SqliteTransactionConnectionInstanceOfPrivate;
        readonly string SqliteConnectionInstanceOfPrivate;

        //public static SqliteConnection? TransactionConnection;
        //public static DbTransaction? Transaction;

        public TransactionService()
        {
            if (!Directory.Exists(DirectoryPath))
                Directory.CreateDirectory(DirectoryPath);
            // transaction
            SqliteTransactionConnectionInstanceOfPrivate = new SqliteConnectionStringBuilder
            {
                DataSource = DataSourceTransaction,
                Mode = SqliteOpenMode.ReadWriteCreate,
                Cache = SqliteCacheMode.Private,
                Pooling = true
            }.ToString();

            SqliteConnectionInstanceOfPrivate = new SqliteConnectionStringBuilder
            {
                DataSource = DataSource,
                Mode = this is iTableReaderService ? SqliteOpenMode.ReadOnly : SqliteOpenMode.ReadWriteCreate,
                Cache = SqliteCacheMode.Private,
                Pooling = true
            }.ToString();

            using (var connection = new SqliteConnection(SqliteTransactionConnectionInstanceOfPrivate))
            {
                connection.Open();
                using (SqliteCommand command = connection.CreateCommand())
                {
                    // status 0创建 1成功 4失败
                    // tables 涉及的表
                    command.CommandText = @$"CREATE TABLE IF NOT EXISTS Transactions(tranid INTEGER PRIMARY KEY,status int, tables varchar,createDate long, complatedDate long)";
                    command.ExecuteNonQuery();
                }
            }
        }

        public async Task BeginTransactionAsync(long tranId, string[] tables, bool isLockTableDB)
        {
            await using (var connection = new SqliteConnection(SqliteTransactionConnectionInstanceOfPrivate))
            {
                await connection.OpenAsync();
                await using (SqliteCommand command = connection.CreateCommand())
                {
                    // status 0创建 1成功 4失败
                    // tables 涉及的表
                    command.CommandText = @$"insert into Transactions(tranid,status, tables,createDate, complatedDate) values({tranId},0,'{string.Join(',', tables)}',{DateTime.Now.Ticks - new DateTime(2022, 03, 12).Ticks},0);SELECT last_insert_rowid();";
                    command.ExecuteNonQuery();
                }
            }
            Console.WriteLine("BeginTransactionAsync:" + tranId);
            await iTransaction.BeginTransactionAsync(tranId, isLockTableDB); // 死锁

            // 并发不安全
            //TransactionConnection = new SqliteConnection(this.SqliteConnectionInstanceOfPrivate);
            //TransactionConnection.Open();
            //Transaction = await TransactionConnection.BeginTransactionAsync();
        }

        public async Task CommitTransactionAsync(long tranId)
        {
            await iTransaction.CommitAsync(tranId);
        }

        public async Task RollbackAsync(long tranId)
        {
            await iTransaction.RollbackAsync(tranId);
        }

        public async Task ComplateTransactiondAsync(long tranId)
        {
            await iTransaction.DisposeAsync(tranId);

            await using (var connection = new SqliteConnection(SqliteTransactionConnectionInstanceOfPrivate))
            {
                await connection.OpenAsync();
                await using (SqliteCommand command = connection.CreateCommand())
                {
                    // status 0创建 1成功 4失败
                    // tables 涉及的表
                    command.CommandText = @$"update Transactions set status = 1,complatedDate={DateTime.Now.Ticks - new DateTime(2022, 03, 12).Ticks} where rowid = {tranId}";
                    await command.ExecuteNonQueryAsync();
                }
            }
        }

        public async Task ErrorTransactiondAsync(long tranId)
        {
            await iTransaction.DisposeAsync(tranId);

            await using (var connection = new SqliteConnection(SqliteTransactionConnectionInstanceOfPrivate))
            {
                await connection.OpenAsync();
                await using (SqliteCommand command = connection.CreateCommand())
                {
                    // status 0创建 1成功 4失败
                    // tables 涉及的表
                    command.CommandText = @$"update Transactions set status = 4,complatedDate={DateTime.Now.Ticks - new DateTime(2022, 03, 12).Ticks} where rowid = {tranId}";
                    await command.ExecuteNonQueryAsync();
                }
            }
        }


    }
}
